package it.interazionemultimodale.twitterrecognizer.twitterutility;

import it.interazionemultimodale.twitterrecognizer.ui.HomeActivity;
import it.interazionemultimodale.twitterrecognizer.ui.TweetAdapter;
import it.interazionemultimodale.twitterrecognizer.utility.Methods;
import it.interazionemultimodale.twitterrecognizer.utility.Variables;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.LinkedList;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.speech.tts.TextToSpeech;
import android.webkit.WebView;
import twitter4j.Paging;
import twitter4j.ResponseList;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;

public class TwitterManager
{
	//Twitter utilities and settings
	private static final String TWITTER_CONSUMER_KEY = "CqGTF6X7AQa05IQFvjysdg";
	private static final String TWITTER_CONSUMER_SECRET = "JviAvX4zNPHKjXFYQ2ojoYSsFS97dYmXPLHngm6ZZQ";
	private static final String TWITTER_CALLBACK_URL = "twitter-client:///";
	private static final String URL_TWITTER_OAUTH_VERIFIER = "oauth_verifier";
	
	private static Twitter twitter = null;
	private static RequestToken requestToken = null;
	private static boolean isTwitterAuthenticated = false;
	
	private TwitterManager()
	{
	}
	
	//Returns a new Twitter instance
	private static Twitter getTwitterInstance()
	{
		if (twitter == null || isTwitterAuthenticated)
		{
			twitter = new TwitterFactory().getInstance();
			twitter.setOAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
			isTwitterAuthenticated = false;
		}
			
		return twitter;
	}
	
	//Returns a new authenticated Twitter instance
	private static Twitter getAuthenticatedTwitterInstance()
	{
		if (twitter == null || !isTwitterAuthenticated)
		{
			String accessToken = Variables.mSharedPreferences.getString(Variables.KEY_OAUTH_TOKEN, null);
			String accessTokenSecret = Variables.mSharedPreferences.getString(Variables.KEY_OAUTH_SECRET, null);
			if (accessToken == null || accessTokenSecret == null)
				twitter = null;
			else
			{
				twitter = new TwitterFactory().getInstance();
				twitter.setOAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
				twitter.setOAuthAccessToken(new AccessToken(accessToken, accessTokenSecret));
				isTwitterAuthenticated = true;
			}
		}
		return twitter;
	}
	
	//Loads twitter login web page visualized into a webView. It do that calling an asynctask
	public static void loadLoginWebPage(WebView webView)
	{
		LoadLoginWebPageTask task = (new TwitterManager()).new LoadLoginWebPageTask(webView);
		task.execute();
	}
	
	private class LoadLoginWebPageTask extends AsyncTask<Void, Void, Void>
	{	
		private WebView webView;
		
		public LoadLoginWebPageTask(WebView webView)
		{
			this.webView = webView;
		}
		
		@Override
		protected Void doInBackground(Void... params)
		{	
			try
			{
				requestToken = getTwitterInstance().getOAuthRequestToken(TWITTER_CALLBACK_URL);
			}
			catch (TwitterException te)
			{
				System.err.println("Impossibile scaricare pagina di accesso");
				te.printStackTrace();
				requestToken = null;
			}
			return null;
		}
		
		@Override
		protected void onPostExecute(Void param)
		{
			if (requestToken != null)
			{
				System.out.println("here");
				this.webView.loadUrl(requestToken.getAuthenticationURL());
			}
			else
				this.webView.loadUrl("http://about:blank");
		}
	}
	
	
	public static void saveAccountAndLoadHome(String url, Context context, Intent intent)
	{
		SaveAccountAndLoadHome task = (new TwitterManager()).new SaveAccountAndLoadHome(context, intent);
		task.execute(url);
	}
	
	private class SaveAccountAndLoadHome extends AsyncTask<String, Void, Void>
	{	
		private Context context;
		private Intent intent;
		private ProgressDialog dialog;
		
		public SaveAccountAndLoadHome(Context context, Intent intent)
		{
			this.intent = intent;
			this.context = context;
			this.dialog = new ProgressDialog(context);
		}
		
		@Override
		protected void onPreExecute()
		{
			this.dialog.setMessage("Caricamento in corso...");
			this.dialog.setCancelable(false);
			this.dialog.show();
		}
		
		@Override
		protected Void doInBackground(String... params)
		{
			for (String url : params)
			{	
				Uri uri = Uri.parse(url);
				String oAuthVerifier = uri.getQueryParameter(URL_TWITTER_OAUTH_VERIFIER);
				
				AccessToken accessToken = null;
				try
				{
					accessToken = getTwitterInstance().getOAuthAccessToken(requestToken, oAuthVerifier);
					
					//Save access info into shared app preferences
					Editor editor = Variables.mSharedPreferences.edit();
					editor.putString(Variables.KEY_OAUTH_TOKEN, accessToken.getToken());
					editor.putString(Variables.KEY_OAUTH_SECRET, accessToken.getTokenSecret());
					editor.putBoolean(Variables.KEY_TWITTER_LOGIN, true);
					editor.commit();
				}
				catch (TwitterException te)
				{
					System.err.println("Impossibile scaricare pagina di accesso");
					te.printStackTrace();
				}
			}
			
			return null;
		}
		
		@Override
		protected void onPostExecute(Void param)
		{
			this.intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
				this.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
			this.dialog.dismiss();
			context.startActivity(this.intent);
		}
	}
	
	
	public static void downloadAndVisualizeTweets(HomeActivity homeActivity, TweetAdapter adapter, TextToSpeech tts, Variables.TwitterTaskCommand command, boolean dialog)
	{
		DownloadAndVisualizeTweets task = (new TwitterManager()).new DownloadAndVisualizeTweets(homeActivity, adapter, tts, command, dialog);
		task.execute();
	}
	
	private class DownloadAndVisualizeTweets extends AsyncTask<Void, Void, LinkedList<TweetInfo>>
	{
		private HomeActivity homeActivity;
		private TweetAdapter adapter;
		private TextToSpeech tts;
		private Variables.TwitterTaskCommand command;
		private ProgressDialog progressDialog = null;
		
		public DownloadAndVisualizeTweets(HomeActivity homeActivity, TweetAdapter adapter, TextToSpeech tts, Variables.TwitterTaskCommand command, boolean dialog)
		{
			this.homeActivity = homeActivity;
			this.adapter = adapter;
			this.tts = tts;
			this.command = command;
			if (dialog)
				this.progressDialog = new ProgressDialog(homeActivity);
		}
		
		@Override
		protected void onPreExecute()
		{
			if (this.progressDialog != null)
			{
				this.progressDialog.setMessage("Caricamento in corso...");
				this.progressDialog.setCancelable(false);
				this.progressDialog.show();
			}
		}
		
		@Override
		protected LinkedList<TweetInfo> doInBackground(Void... params)
		{
			LinkedList<TweetInfo> tweetList = new LinkedList<TweetInfo>();
			try
			{
				Paging paging = new Paging();
				
				switch (this.command)
				{
					case HOME_TWEETS:
						paging.count(Variables.INITIAL_TWEETS_TO_VISUALIZE);
						break;
						
					case OLDER_TWEETS:
						paging.maxId(this.adapter.getLastId() - 1);
						paging.count(Variables.OLDER_TWEETS_TO_VISUALIZE);
						break;
						
					case NEW_TWEETS:
						paging.sinceId(this.adapter.getFirstId());
						break;
				}
				
				ResponseList<twitter4j.Status> responseList = getAuthenticatedTwitterInstance().getHomeTimeline(paging);
				for (twitter4j.Status status : responseList)
				{
					Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(status.getUser().getOriginalProfileImageURL()).getContent());					
					tweetList.add(new TweetInfo(status, Bitmap.createScaledBitmap(bitmap, 100, 100 * bitmap.getHeight() / bitmap.getWidth(), false)));
				}
			}
			catch (TwitterException te)
			{
				System.err.println("Eccezione sull'oggetto Twitter");
				te.printStackTrace();
			}
			catch (IOException ioe)
			{
				System.err.println("Eccezione I/O");
				ioe.printStackTrace();
			}
			
			return tweetList;
		}
		
		@Override
		protected void onPostExecute(LinkedList<TweetInfo> tweetList)
		{
			switch (this.command)
			{
				case HOME_TWEETS:
					if (tweetList.size() > 0)
					{
						this.adapter.addTweets(tweetList);
						
						//GUI management
						this.homeActivity.setListAdapter(adapter);
						this.homeActivity.enableButtons();
						this.homeActivity.disableHomeProgressBar();
						this.homeActivity.enableListView();
					}
					else
						Methods.showToast(this.homeActivity, Variables.NO_TWEETS_TO_VISUALIZE_MESSAGE);
					break;
				case OLDER_TWEETS:
					if (tweetList.size() > 0)
					{
						this.adapter.addTweets(tweetList);
						Methods.showToast(this.homeActivity, (tweetList.size() == 1) ? Variables.OLDER_TWEET_VISUALIZED_MESSAGE : tweetList.size() + " " + Variables.OLDER_TWEETS_VISUALIZED_MESSAGE);
						if (this.tts != null)
							tts.speak((tweetList.size() == 1) ? Variables.OLDER_TWEET_VISUALIZED_MESSAGE : tweetList.size() + " " + Variables.OLDER_TWEETS_VISUALIZED_MESSAGE, TextToSpeech.QUEUE_ADD, null);
					}
					else
					{
						Methods.showToast(this.homeActivity, Variables.NO_OLDER_TWEETS_TO_VISUALIZE_MESSAGE);
						if (this.tts != null)
							tts.speak(Variables.NO_OLDER_TWEETS_TO_VISUALIZE_MESSAGE, TextToSpeech.QUEUE_ADD, null);
					}
					Variables.OLDER_TWEETS_TO_VISUALIZE = Variables.PREDEFINED_OLDER_TWEETS_TO_VISUALIZE;
					
					//GUI management
					this.homeActivity.disableFooterProgressBar();
					break;
				case NEW_TWEETS:
					if (tweetList.size() > 0)
					{
						this.adapter.pushTweets(tweetList);
						Methods.showToast(this.homeActivity, (tweetList.size() == 1) ? Variables.NEW_TWEET_VISUALIZED_MESSAGE : tweetList.size() + " " + Variables.NEW_TWEETS_VISUALIZED_MESSAGE);
						if (this.tts != null)
							tts.speak((tweetList.size() == 1) ? Variables.NEW_TWEET_VISUALIZED_MESSAGE : tweetList.size() + " " + Variables.NEW_TWEETS_VISUALIZED_MESSAGE, TextToSpeech.QUEUE_ADD, null);
					}
					else
					{
						Methods.showToast(this.homeActivity, Variables.NO_NEW_TWEETS_TO_VISUALIZE_MESSAGE);
						if (this.tts != null)
							tts.speak(Variables.NO_NEW_TWEETS_TO_VISUALIZE_MESSAGE, TextToSpeech.QUEUE_ADD, null);
					}
					
					//GUI management
					this.homeActivity.listViewRefreshCompleted();
					break;
			}
			
			if (this.progressDialog != null)
			{
				this.progressDialog.dismiss();
				
				//GUI management
				this.homeActivity.enableButtons();
			}
		}
	}
	
	public static void postTweet(String text, Context context)
	{
		PostTweet task = (new TwitterManager()).new PostTweet(context);
		task.execute(text);
	}
	
	private class PostTweet extends AsyncTask<String, Void, Boolean>
	{
		private ProgressDialog progressDialog;
		
		public PostTweet(Context context)
		{
			this.progressDialog = new ProgressDialog(context);
		}
		
		@Override
		protected void onPreExecute()
		{
			this.progressDialog.setMessage("Pubblicazione del tweet in corso.\nAttendere...");
			this.progressDialog.setCancelable(false);
			this.progressDialog.show();
		}
		
		@Override
		protected Boolean doInBackground(String... text)
		{
			try
			{
				getAuthenticatedTwitterInstance().updateStatus(text[0]);
			}
			catch (TwitterException te)
			{
				System.out.println("Eccezione twitter");
				te.printStackTrace();
				return false;
			}
			return true;
		}
		
		@Override
		protected void onPostExecute(Boolean onSuccess)
		{
			this.progressDialog.dismiss();
			if (onSuccess)
			{
				Methods.showToast(this.progressDialog.getContext(), "Nuovo tweet pubblicato");
				Variables.textToSpeech.speak("Tweet pubblicato", TextToSpeech.QUEUE_FLUSH, null);
			}
			else
				Variables.textToSpeech.speak("Errore nella pubblicazione del tweet. Riprovare", TextToSpeech.QUEUE_FLUSH, null);
		}
	}
	
	public static void logout()
	{
		if (twitter != null)
		{
			twitter.setOAuthAccessToken(null);
			twitter.shutdown();
		}
		
		twitter = null;
		requestToken = null;
		isTwitterAuthenticated = false;
	}
}
